#pragma once

#include "my_mem.h"
#include "my_thread_mem.h"
#include "my_syscall.h"

#define MY_THREAD_DATA_ITEMS                (32)

typedef struct my_thread_base_s             my_thread_base_t;
typedef void *(*my_thread_base_execute_pt)(my_thread_base_t *thread_base);


struct my_thread_base_s {
    const char *                            tag;
    my_thread_base_execute_pt               execute_pt;
    void                                    *data;
    my_thread_t                             tid;
    my_thread_mem_freelists_t               *mem_freelists;
    my_thread_4kaligned_mem_freelists_t     *aligned_mem_freelists;

    // save some thread-local resources.
    // such as http session pool, etc.
    void                                    *private_data[MY_THREAD_DATA_ITEMS];
};


void my_thread_base_start(
    const char *tag,
    my_thread_base_t *thread_base,
    my_thread_base_execute_pt execute_pt,
    void *data,
    int64_t mem_freelists_level,
    int64_t aligned_mem_freelists_level);

void my_thread_base_join(my_thread_base_t *thread_base, void **ret);

my_thread_base_t *current_thread_base();

void *my_thread_malloc(size_t size);

void my_thread_free(void *ptr);

static inline void *
my_thread_calloc(size_t size)
{
    void *ptr = my_thread_malloc(size);
    bzero(ptr, size);
    return ptr;
}



void *my_thread_aligned_malloc(size_t size);

void my_thread_aligned_free(void *ptr);


static inline void
my_thread_data_store(int idx, void *data)
{
    assert(idx >= 0 && idx < MY_THREAD_DATA_ITEMS);
    my_thread_base_t *thread_base = current_thread_base();
    assert(thread_base != NULL);
    thread_base->private_data[idx] = data;
}

static inline void *
my_thread_data_get(int idx)
{
    assert(idx >= 0 && idx < MY_THREAD_DATA_ITEMS);
    my_thread_base_t *thread_base = current_thread_base();
    assert(thread_base != NULL);
    return thread_base->private_data[idx];
}

